/**
* Copyright (C) 2007 Pedro Miller Rabinovitch.
* http://www.opensource.org/licenses/mit-license.php
*
* Basically, feel free to use it however you want to.
* Please give me credit where appropriate.
*
* Pedro "Shade" Miller, gmail user: pedromr
* http://exodia.org
*
* @author Miller
*
* $Id: Agent.as 11 2007-12-17 23:03:04Z pedromr $
*/
package org.exodia.seeds.model {
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import org.exodia.seeds.model.World;
	import org.exodia.math.Vector3D;
	import org.exodia.seeds.behaviours.IBehaviour;

	/**
	 * Model of an Agent in a 3D environment. Does not imply
	 * graphical representation.
	 **/
	public class Agent extends EventDispatcher {
		private var _world:World;
		
		public var maxSpeed:Number;
		public var maxForce:Number;
		public var sensorRangeSquared:Number;
		
		public var neighbours:Array;
		
		private var _speed : Vector3D;
		private var _thrust : Vector3D;
		private var _position : Vector3D;
		private var _radius : Number;
		private var _mass : Number;
		
		private var _behaviourList : Array;
		
		public var data:Object;
		
		public function get radius() : Number {
			return _radius;
		}
		
		public function set radius(value:Number) : void {
			_radius = value;
			_mass = Math.PI * _radius * _radius * 0.005;
		}
		
		public function get position() : Vector3D {
			//this.dispatchEvent(new Event(Event.CHANGE));
			return _position;
		}
		
		public function set thrust(vec:Vector3D) : void {
			_thrust.copyFrom( vec );
		}
		
		public function get thrust() : Vector3D {
//trace( "getting thr "+_thrust );
			return _thrust;
		}
		
		public function get speed() : Vector3D {
			return _speed;
		}
		
		public function Agent( world:World ) {
			_world = world;
			_speed = new Vector3D();
			_thrust = new Vector3D();
			_position = new Vector3D();
			_behaviourList = new Array();
			
			radius = 10;
			maxSpeed = 1;
			maxForce = 0.1;
			sensorRangeSquared = 150*150;
			
			neighbours = [];
			
			data = {};
			
			_world.addAgent( this );
		}
		
		public function addBehaviour( behaviour : IBehaviour ) {
			if( _behaviourList.indexOf( behaviour ) == -1 ) {
				_behaviourList.push( behaviour );
				behaviour.initialize( this );
			}
		}
		
		private function extrapolateDelta( target:Vector3D, vector:Vector3D, deltaMS:int ) : void {
			target.copyFrom( vector ).mul( deltaMS );
		}
		
		public function moveStep( deltaMS:int ) : void {
			var change:Vector3D = Vector3D.create();

			if(false)
			{
				trace( "1 thrust "+_thrust );
				trace( "1 speed "+_speed );
				trace( "1 pos "+_position );
			}

			_thrust.length = Math.min( _thrust.length, maxForce );
			change.copyFrom( _thrust ).mul( deltaMS );
			change.mul( 1 / _mass );
			_speed.add( change );
			//trace( "1c speed "+[maxSpeed,_speed] );
			_speed.length = Math.min( _speed.length, maxSpeed );
			//trace( "1b speed "+[_speed, change, maxSpeed] );

			change.copyFrom( _speed ).mul( deltaMS );

			if ( !_world.checkMobility( this, change )) {
				// bump. Cut speed... or not?
				if ( change.x == 0 )
					_speed.x = 0;
				if ( change.y == 0 )
					_speed.y = 0;
			}
			_position.add( change );
			
			if(false)
			{
				trace( "2 thrust "+_thrust );
				trace( "2 speed "+_speed );
				trace( "2 pos "+_position );
			}
		}
		
		public function tick( deltaMS:int ) : void {
//trace( "in tick "+deltaMS );
			thrust.length = 0;
			for each( var behaviour:IBehaviour in _behaviourList ) {
				behaviour.tick( this, deltaMS );
			}
//trace( "out tick "+[deltaMS,_thrust] );
		}
	}
	
}
